/*
 * @Description:
 * @Author: Junhuang
 * @Date: 2022-05-29 11:40:15
 * @LastEditTime: 2022-06-07 20:00:31
 * @LastEditors: Junhuang
 * @Reference:
 */
'use strict';

const Controller = require('egg').Controller;

class PlanController extends Controller {
  async index() {
    const { ctx, app } = this;
    const user_id = ctx.authUser.id;

    const Op = app.Sequelize.Op;
    // 获取当天23:59:59秒，及 获取当天00:00:00的方法
    // 当天23点59分59秒
    // new Date(new Date().toLocaleDateString()).getTime() + 24 * 60 * 60 * 1000 - 1
    // 当天00点00分00秒
    // new Date(new Date().toLocaleDateString()).getTime()

    // 找到已过期的但并未处理的任务，并将其状态设置为-1
    const tasks = await app.model.Plan.findAll({
      where: {
        user_id,
        status: 0,
        pdate: {
          [Op.lt]: new Date(new Date().toLocaleDateString()).getTime(),
        },
      },
    });

    if (tasks && tasks.length > 0) {
      await Promise.all(
        tasks.map(async item => {
          item.status = -1;
          await item.save();
        })
      );
    }

    const history = await app.model.Plan.findAll({
      where: {
        user_id,
        status: [ -1, 1, 2 ],
      },
      order: [[ 'pdate', 'DESC' ]],
    });

    const lastest = await app.model.Plan.findOne({
      where: {
        user_id,
        status: 0,
        pdate: new Date(new Date().toLocaleDateString()),
      },
      order: [[ 'pdate', 'ASC' ]],
    });

    const overdued = history.filter(item => item.status === -1);

    let submitedRate = 100;

    if (history.length > 0) {
      submitedRate = 100 - parseInt((overdued.length / history.length) * 100);
    }

    let avarageScore = 100;
    const scored = history.filter(item => item.status === 2);
    if (scored.length > 0) {
      let score = 0;
      scored.forEach(el => {
        if (el.rate) {
          score += el.rate;
        }
      });
      avarageScore = parseInt((score / (scored.length * 10)) * 100);
    }

    let notice;
    const adviceds = await app.model.Plan.findAll({
      where: {
        user_id,
        status: 2,
        adviced_time: {
          [Op.gt]: new Date(new Date().toLocaleDateString()).getTime() - 7 * 24 * 60 * 60 * 1000,
        },
      },
      order: [[ 'adviced_time', 'DESC' ]],
    });
    const adviced = adviceds.find(item => { return (item.feedback_time === 0); });
    if (adviced) {
      notice = `老师对你的[${adviced.pdate}${adviced.title}]作业进行了点评,快去看看吧!`;
    }

    if (ctx.authUser.type === 2) {
      const rank = await app.model.Rank.findOne({
        where: {
          user_id,
        },
      });

      if (rank) {
        rank.on_time_rate = submitedRate;
        rank.score = avarageScore;
        // console.log('rank=', rank);
        await rank.save();
      } else {
        await app.model.Rank.create({
          user_id,
          on_time_rate: submitedRate,
          score: avarageScore,
        });
      }
    }

    // 数据库中存储整数，但是对外给出时是1-5之间且有半星的情况
    history.forEach(item => {
      if (item.rate) {
        item.rate = item.rate / 2;
      }
    });


    if (lastest && lastest.rate) {
      lastest.rate = lastest.rate / 2;
    }


    ctx.apiSuccesss({
      history: JSON.parse(JSON.stringify(history)),
      lastest: JSON.parse(JSON.stringify(lastest)),
      submitedRate,
      avarageScore,
      notice,
    });
  }

  // 获取特定周的计划
  // /plan_week
  async week_list() {
    const { ctx, app } = this;
    const user = ctx.authUser;
    if (user.type !== 3) {
      return ctx.apiFail('只有老师才有访问该接口的权限');
    }
    const Op = app.Sequelize.Op;
    ctx.validate({
      begin: {
        required: true,
        type: 'string',
        desc: '开始日期',
      },
      end: {
        required: true,
        type: 'string',
        desc: '结束日期',
      },
    });
    const { begin, end } = ctx.query;
    const beginDate = new Date(begin);
    const endDate = new Date(end);
    if ((beginDate.toString().indexOf('Invalid') !== -1)
     || endDate.toString().indexOf('Invalid') !== -1) {
      return ctx.apiFail('参数[开始日期]或[结束日期]格式错误！');
    }
    endDate.setDate(endDate.getDate() + 1);

    let plans = await app.model.Plan.findAll({
      where: {
        pdate: {
          [Op.gte]: beginDate,
          [Op.lt]: endDate,
        },
      },
    });
    plans = JSON.parse(JSON.stringify(plans));

    let users = await app.model.User.findAll({
      where: {
        type: 2,
        status: 1,
      },
    });
    users = JSON.parse(JSON.stringify(users));
    users.forEach(u => {
      const temps = plans.filter(item => item.user_id === u.id && (item.status !== 0));
      const history = [];
      if (temps && temps.length > 0) {
        temps.forEach(it => {
          history.push(new Date(it.pdate).toLocaleDateString());
        });
      }
      u.history = history;

      const temp2 = plans.filter(item => item.user_id === u.id);
      const dates = [];
      if (temp2 && temp2.length > 0) {
        temp2.forEach(it => {
          dates.push(new Date(it.pdate).toLocaleDateString());
        });
      }
      u.dates = dates;
      u.user_id = u.id;
    });

    return ctx.apiSuccesss(users);
  }

  // 更新计划
  async save() {
    const { ctx, app } = this;
    const user = ctx.authUser;
    if (user.type !== 3) {
      return ctx.apiFail('只有老师才有访问该接口的权限');
    }
    const Op = app.Sequelize.Op;
    const { submited, begin, end } = ctx.request.body;

    if (submited && submited.length === 0) {
      // is ok
    } else {
      ctx.apiFail('提交的计划数据为空！');
    }
    ctx.validate({
      begin: {
        required: true,
        type: 'string',
        desc: '开始日期',
      },
      end: {
        required: true,
        type: 'string',
        desc: '结束日期',
      },
    });

    const beginDate = new Date(begin);
    const endDate = new Date(end);
    if ((beginDate.toString().indexOf('Invalid') !== -1)
     || endDate.toString().indexOf('Invalid') !== -1) {
      return ctx.apiFail('参数[开始日期]或[结束日期]格式错误！');
    }
    endDate.setDate(endDate.getDate() + 1);

    const plans = await app.model.Plan.findAll({
      where: {
        pdate: {
          [Op.gte]: beginDate,
          [Op.lt]: endDate,
        },
      },
    });

    const addPlans = []; // 新增计划id列表
    const deletePlans = []; // 删除计划id列表

    let transaction;
    try {
      // 建立事务对象
      transaction = await this.ctx.model.transaction();
      // console.log('submited', submited);
      // console.log('plans', plans);
      await Promise.all(
        submited.map(async item => {
          const plan = plans.find(p =>
            (new Date(p.pdate).toLocaleDateString() === new Date(item.pdate).toLocaleDateString())
            && p.user_id === item.user_id
          );
          if (item.planed && !plan) {
            const validDate = new Date();
            validDate.setDate(validDate.getDate());
            // console.log(new Date(item.pdate).toLocaleDateString(), validDate.toLocaleDateString());
            // 计划的日期必须要大于等于当前日期
            if (new Date(item.pdate).toLocaleDateString() >= validDate.toLocaleDateString()) {
              const existed = await app.model.Plan.findOne({
                where: {
                  user_id: item.user_id,
                  pdate: new Date(item.pdate),
                },
              }, { transaction });
              if (!existed) {
                const newPlan = await app.model.Plan.create({
                  user_id: item.user_id,
                  pdate: item.pdate,
                  status: 0,
                  title: '日常计划',
                }, { transaction });
                addPlans.push(newPlan.id);
              }
            }
          } else if ((!item.planed) && plan && plan.status === 0) {
            deletePlans.push(plan.id);
            await plan.destroy({ transaction });
          }
        })
      );
      await transaction.commit();
      return ctx.apiSuccesss({ addPlans, deletePlans });
    } catch (err) {
      await transaction.rollback();
      return ctx.apiFail('更新计划失败:' + err);
    }
  }

  // 老师对作业点评
  async advice() {
    const { ctx, app } = this;
    const user = ctx.authUser;
    if (user.type !== 3) {
      return ctx.apiFail('只有老师才有访问该接口的权限');
    }
    const { rate, advice } = ctx.request.body;
    ctx.validate({
      id: {
        required: true,
        type: 'int',
        desc: '计划id',
      },
      rate: {
        required: true,
        type: 'number',
        desc: '评分',
      },
      advice: {
        required: true,
        type: 'string',
        desc: '评价',
      },
    });

    const task = await app.model.Plan.findOne({
      where: {
        id: ctx.params.id,
      },
      include: [{
        model: app.model.User,
      }],
    });

    if (!task) {
      return ctx.apiFail('无此任务！');
    }

    if (task.status !== 1) {
      return ctx.apiFail('此任务不为待点评状态，不能点评');
    }

    task.rate = rate * 2 > 10 ? 10 : rate * 2;
    task.advice = advice;
    task.status = 2;
    task.adviced_time = new Date();
    task.save();

    return ctx.apiSuccesss(task);

  }

  // 获得某个任务，学生只能看自己的视频，而老师可以看所有人视频
  // 当老师回复任务后，学生第一次查看该任务，则会更新此任务的feedback_time
  // /plan/:id
  async get() {
    const { ctx, app } = this;
    const user = ctx.authUser;
    ctx.validate({
      id: {
        required: true,
        type: 'int',
        desc: '计划id',
      },
    });
    const task = await app.model.Plan.findOne({
      where: {
        id: ctx.params.id,
      },
      include: [{
        model: app.model.User,
      }],
    });
    if (!task) {
      return ctx.apiFail('无此任务！');
    }

    if (task.user_id === user.id || user.type === 3) {
      // is ok
    } else {
      return ctx.apiFail('您没有查看该任务的权限！');
    }
    // 如果当前任务老师已经点评了，当学生第一次看此任务时，需要设置feedback_time
    if (task.status === 2 && (!task.feedback_time)) {
      task.feedback_time = new Date();
      await task.save();
    }
    if (task.rate) {
      task.rate = task.rate / 2;
    }

    return ctx.apiSuccesss(task);
  }

  // 上传视频
  // /plan/:id/video
  async updateVideo() {
    const { ctx, app } = this;
    const user_id = ctx.authUser.id;
    const { video } = ctx.request.body;
    ctx.validate({
      id: {
        required: true,
        type: 'int',
        desc: '计划id',
      },
      video: {
        required: true,
        type: 'string',
        desc: '视频地址',
      },
    });


    const task = await app.model.Plan.findByPk(ctx.params.id);
    if (!task) {
      return ctx.apiFail('无此任务！');
    }

    if (task.user_id !== user_id) {
      return ctx.apiFail('此任务不属于当前用户，无法操作！');
    }

    if (task.video && task.video.length > 0) {
      task.video2 = video;
    } else {
      task.video = video;
    }

    task.uploaded_time = new Date();
    if (task.status === 0) {
      task.status = 1;
    }
    await task.save();

    return ctx.apiSuccesss(task);
  }

  // 获取特定时间段，所有学生的工作计划
  async getStudentsPlan() {
    const { ctx, app } = this;
    const user = ctx.authUser;
    if (user.type !== 3) {
      return ctx.apiFail('只有老师才有访问该接口的权限');
    }
    const Op = app.Sequelize.Op;
    ctx.validate({
      begin: {
        required: true,
        type: 'string',
        desc: '开始日期',
      },
      end: {
        required: true,
        type: 'string',
        desc: '结束日期',
      },
    });
    const { begin, end } = ctx.query;
    const beginDate = new Date(begin);
    const endDate = new Date(end);
    if ((beginDate.toString().indexOf('Invalid') !== -1)
     || endDate.toString().indexOf('Invalid') !== -1) {
      return ctx.apiFail('参数[开始日期]或[结束日期]格式错误！');
    }
    endDate.setDate(endDate.getDate() + 1);

    // 找到已过期的但并未处理的任务，并将其状态设置为-1
    const tasks = await app.model.Plan.findAll({
      where: {
        status: 0,
        pdate: {
          [Op.lt]: new Date(new Date().toLocaleDateString()).getTime(),
        },
      },
    });

    if (tasks && tasks.length > 0) {
      await Promise.all(
        tasks.map(async item => {
          item.status = -1;
          await item.save();
        })
      );
    }

    const res = await app.model.User.findAll({
      where: {
        type: 2,
        status: 1,
      },
      include: [{
        model: app.model.Plan,
        where: {
          pdate: {
            [Op.gte]: beginDate,
            [Op.lt]: endDate,
          },
        },
      }],
      order: [[ 'description', 'ASC' ], [ 'id', 'ASC' ], [ 'plans', 'pdate', 'DESC' ]],
    });

    const students = [];
    res.forEach(item => {
      const total = item.plans.length;
      const waiting = (item.plans.filter(i => i.status === 0)).length;
      const submited = (item.plans.filter(i => i.status === 1)).length;
      const adviced = (item.plans.filter(i => i.status === 2)).length;
      const expired = (item.plans.filter(i => i.status === -1)).length;
      const plans = [];
      item.plans.forEach(it => {
        plans.push({
          id: it.id,
          pdate: it.pdate,
          title: it.title,
          status: it.status,
          rate: it.rate ? it.rate / 2 : 0,
        });
      });
      students.push({
        id: item.id,
        nickname: item.nickname,
        description: item.description,
        total,
        waiting,
        submited,
        adviced,
        expired,
        plans,
      });
    });

    return ctx.apiSuccesss(students);
  }

  // 获取莫学生的作品分页，不需要鉴权
  // 路由：/plan_list_page/:page
  // 访问示例： http://127.0.0.1:7001/user_plans/1?user_id=1&limit=10
  async getPlansPage() {
    const { ctx, app } = this;
    ctx.validate({
      user_id: {
        type: 'int',
        required: true,
        desc: '用户id',
      },
      page: {
        required: true,
        type: 'int',
        desc: '第几页',
      },
      limit: {
        required: false,
        type: 'int',
        desc: '每页几条',
      },
    });
    const user_id = ctx.query.user_id;

    const plans = await ctx.page(app.model.Plan, {
      user_id,
      status: 2,
    });

    return ctx.apiSuccesss(plans);
  }

}

module.exports = PlanController;
